""" 指标暴露（QPS/延迟/错误率）"""
"""指标导出器（Prometheus格式指标暴露）"""
import threading
from typing import Dict, Any, Callable
from fin_senti_entity_platform.utils.logger import Logger
from fin_senti_entity_platform.utils.config_loader import ConfigLoader
from fin_senti_entity_platform.utils.constants import PERFORMANCE_METRICS


class MetricsExporter:
    """指标导出器类，用于导出系统和模型性能指标"""
    
    def __init__(self):
        """初始化指标导出器"""
        self.logger = Logger().get_logger(__name__)
        self.config = ConfigLoader().get_config('monitor', 'prometheus')
        self.metrics = {}
        self.metric_callbacks = {}
        self._lock = threading.Lock()
        self.http_server = None
    
    def register_metric(self, name: str, metric_type: str, description: str):
        """注册一个新的指标
        
        Args:
            name: 指标名称
            metric_type: 指标类型（counter, gauge, histogram, summary）
            description: 指标描述
        """
        with self._lock:
            if name not in self.metrics:
                self.metrics[name] = {
                    'type': metric_type,
                    'description': description,
                    'value': 0 if metric_type == 'counter' else None,
                    'labels': {},
                    'samples': [] if metric_type in ['histogram', 'summary'] else None
                }
                self.logger.info(f"已注册指标: {name} ({metric_type})")
    
    def set_metric(self, name: str, value: float, labels: Dict[str, str] = None):
        """设置指标值
        
        Args:
            name: 指标名称
            value: 指标值
            labels: 指标标签
        """
        with self._lock:
            if name in self.metrics:
                metric = self.metrics[name]
                labels_key = str(labels) if labels else 'default'
                
                if metric['type'] == 'counter':
                    # 计数器累加
                    if labels_key not in metric['labels']:
                        metric['labels'][labels_key] = 0
                    metric['labels'][labels_key] += value
                else:
                    # 其他类型直接设置
                    metric['labels'][labels_key] = value
    
    def register_callback(self, name: str, callback: Callable[[], Dict[str, Any]]):
        """注册指标回调函数
        
        Args:
            name: 指标名称
            callback: 回调函数，返回指标值字典
        """
        with self._lock:
            self.metric_callbacks[name] = callback
    
    def collect_metrics(self) -> str:
        """收集所有指标，生成Prometheus格式的指标数据
        
        Returns:
            str: Prometheus格式的指标数据
        """
        # 先执行所有回调函数更新指标
        self._update_from_callbacks()
        
        result = []
        
        with self._lock:
            for name, metric in self.metrics.items():
                # 添加指标帮助信息
                result.append(f"# HELP {name} {metric['description']}")
                result.append(f"# TYPE {name} {metric['type']}")
                
                # 添加指标数据
                for labels_key, value in metric['labels'].items():
                    if labels_key == 'default':
                        result.append(f"{name} {value}")
                    else:
                        # 解析标签字符串
                        try:
                            import json
                            labels = json.loads(labels_key.replace("'", '"'))
                            labels_str = ','.join([f"{k}={json.dumps(v)}" for k, v in labels.items()])
                            result.append(f"{name}{{{labels_str}}} {value}")
                        except:
                            result.append(f"{name} {value}")
                
            result.append("")  # 确保最后有一个空行
        
        return '\n'.join(result)
    
    def _update_from_callbacks(self):
        """从回调函数更新指标"""
        for name, callback in self.metric_callbacks.items():
            try:
                metrics_data = callback()
                if isinstance(metrics_data, dict):
                    for metric_name, metric_value in metrics_data.items():
                        full_name = f"{name}_{metric_name}" if name else metric_name
                        if full_name not in self.metrics:
                            # 自动注册未注册的指标
                            description = PERFORMANCE_METRICS.get(metric_name, metric_name)
                            self.register_metric(full_name, 'gauge', description)
                        self.set_metric(full_name, metric_value)
            except Exception as e:
                self.logger.error(f"执行指标回调 {name} 失败: {str(e)}")
    
    def start_http_server(self):
        """启动HTTP服务器，暴露指标"""
        if self.http_server is None:
            host = self.config.get('host', '0.0.0.0')
            port = self.config.get('port', 8001)
            
            try:
                from http.server import HTTPServer, BaseHTTPRequestHandler
                
                class MetricsHandler(BaseHTTPRequestHandler):
                    def do_get(self):
                        if self.path == '/metrics':
                            self.send_response(200)
                            self.send_header('Content-Type', 'text/plain; version=0.0.4')
                            self.end_headers()
                            metrics_data = self.server.metrics_exporter.collect_metrics()
                            self.wfile.write(metrics_data.encode('utf-8'))
                        else:
                            self.send_response(404)
                            self.end_headers()
                
                self.http_server = HTTPServer((host, port), MetricsHandler)
                self.http_server.metrics_exporter = self
                
                self._server_thread = threading.Thread(target=self.http_server.serve_forever, daemon=True)
                self._server_thread.start()
                
                self.logger.info(f"指标导出HTTP服务器已启动在 http://{host}:{port}/metrics")
            except Exception as e:
                self.logger.error(f"启动指标导出服务器失败: {str(e)}")
                self.http_server = None
    
    def stop_http_server(self):
        """停止HTTP服务器"""
        if self.http_server is not None:
            self.http_server.shutdown()
            self.http_server = None
            self.logger.info("指标导出HTTP服务器已停止")


# 创建全局实例
global_metrics_exporter = MetricsExporter()


def get_metrics_exporter() -> MetricsExporter:
    """获取指标导出器实例"""
    return global_metrics_exporter